package com.csp.mingyue.oss.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.csp.mingyue.common.core.exception.ServiceException;
import com.csp.mingyue.common.core.utils.FileUtils;
import com.csp.mingyue.common.oss.core.OssClient;
import com.csp.mingyue.common.oss.entity.UploadResult;
import com.csp.mingyue.common.oss.enums.AccessPolicyType;
import com.csp.mingyue.common.oss.factory.OssFactory;
import com.csp.mingyue.oss.api.entity.SysOss;
import com.csp.mingyue.oss.api.vo.SysOssVo;
import com.csp.mingyue.oss.mapper.SysOssMapper;
import com.csp.mingyue.oss.service.SysOssService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * <p>
 * OSS对象存储表 服务实现类
 * </p>
 *
 * @author Strive
 * @since 2023-09-12 09:19:12
 */
@Service
@RequiredArgsConstructor
public class SysOssServiceImpl extends ServiceImpl<SysOssMapper, SysOss> implements SysOssService {

	@Override
	public SysOssVo upload(MultipartFile file) {
		String originalFilename = file.getOriginalFilename();
		String suffix = StrUtil.sub(originalFilename, originalFilename.lastIndexOf("."), originalFilename.length());
		OssClient storage = OssFactory.instance();
		UploadResult uploadResult;
		try {
			uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType());
		}
		catch (IOException e) {
			throw new ServiceException(e.getMessage());
		}

		// 保存文件信息
		return this.buildResult(originalFilename, suffix, storage.getConfigKey(), uploadResult);
	}

	/**
	 * 构建上传文件返回信息
	 * @param originalFilename 原始文件名
	 * @param suffix 文件后缀
	 * @param configKey 配置key
	 * @param uploadResult OSS服务返回结果
	 * @return
	 */
	private SysOssVo buildResult(String originalFilename, String suffix, String configKey, UploadResult uploadResult) {
		SysOss oss = new SysOss();
		oss.setFileUrl(uploadResult.getFileUrl());
		oss.setFileSuffix(suffix);
		oss.setFileName(uploadResult.getFileName());
		oss.setOriginalName(originalFilename);
		oss.setService(configKey);
		this.save(oss);

		SysOssVo sysOssVo = BeanUtil.toBean(oss, SysOssVo.class);
		return this.matchingUrl(sysOssVo);
	}

	/**
	 * 匹配Url
	 * @param oss OSS对象
	 * @return oss 匹配Url的OSS对象
	 */
	private SysOssVo matchingUrl(SysOssVo oss) {
		OssClient storage = OssFactory.instance(oss.getService());

		// 仅修改桶类型为 private 的URL，临时URL时长为120s
		if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) {
			oss.setFileUrl(storage.getPrivateUrl(oss.getFileName(), 120));
		}
		return oss;
	}

	@Override
	public Boolean deleteByOssIds(List<Long> ossIds) {
		List<SysOss> list = this.listByIds(ossIds);
		if (CollUtil.isEmpty(list)) {
			return Boolean.FALSE;
		}

		for (SysOss sysOss : list) {
			OssClient storage = OssFactory.instance(sysOss.getService());
			storage.delete(sysOss.getFileUrl());
		}

		return this.removeBatchByIds(ossIds);
	}

	@Override
	public void download(Long ossId, HttpServletResponse response) throws IOException {
		SysOss sysOss = this.getById(ossId);
		if (ObjectUtil.isNull(sysOss)) {
			throw new ServiceException("文件数据不存在!");
		}
		FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
		response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
		OssClient storage = OssFactory.instance(sysOss.getService());

		try (InputStream inputStream = storage.getObjectContent(sysOss.getFileUrl())) {
			int available = inputStream.available();
			IoUtil.copy(inputStream, response.getOutputStream(), available);
			response.setContentLength(available);
		}
		catch (Exception e) {
			throw new ServiceException(e.getMessage());
		}
	}

}
